package com.nmc.service.manager.impl;

import java.math.BigInteger;
import java.text.DateFormatSymbols;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;

import com.nmc.common.BirthStatusEnum;
import com.nmc.service.dao.BirthDao;
import com.nmc.service.manager.BirthManager;
import com.nmc.service.model.Birth;
import com.nmc.service.model.StatisticsModel;

/**
 * Implementation of BirthManager interface.
 * 
 */
public class BirthManagerImpl extends GenericManagerImpl<Birth, String> implements
		BirthManager {

	private BirthDao birthDao;


	public void setBirthDao(BirthDao birthDao) {
		this.dao = birthDao;
		this.birthDao = birthDao;
	}

	/**
	 * {@inheritDoc}
	 */
	public Birth getBirth(String birthId) {
		return birthDao.get(birthId);
	}

	/**
	 * {@inheritDoc}
	 */
	public List<Birth> getBirths() {
		return birthDao.getAllDistinct();
	}

	/**
	 * {@inheritDoc}
	 */
	public Birth saveBirth(Birth birth) {

		return birthDao.saveBirth(birth);

	}

	/**
	 * {@inheritDoc}
	 */
	public void removeBirth(String birthId) {
		log.debug("removing birth: " + birthId);
		birthDao.remove(birthId);
	}

	/**
	 * {@inheritDoc}
	 */
	public List<Birth> search(String searchTerm) {
		return super.search(searchTerm, Birth.class);
	}
	
	public List<Birth> getHospitalBirthList(int hospitalId){
		  SecurityContext ctx = SecurityContextHolder.getContext();

	        if (ctx.getAuthentication() != null) {
	            Authentication auth = ctx.getAuthentication();
	            UserDetails currentUser = getCurrentUser(auth);
	        }
	        
	        return birthDao.getHospitalBirthList(hospitalId);
	}
	
	public List<Birth> getHospitalBirthListByStatus(int hospitalId, BirthStatusEnum birthStatusEnum,int count){
		  SecurityContext ctx = SecurityContextHolder.getContext();

	        if (ctx.getAuthentication() != null) {
	            Authentication auth = ctx.getAuthentication();
	            UserDetails currentUser = getCurrentUser(auth);
	        }
	        
	        return birthDao.getHospitalBirthListByStatus(hospitalId, birthStatusEnum,count);
	}
	 private UserDetails getCurrentUser(Authentication auth) {
	    	UserDetails currentUser;
	        if (auth.getPrincipal() instanceof UserDetails) {
	            currentUser = (UserDetails) auth.getPrincipal();
	        } else if (auth.getDetails() instanceof UserDetails) {
	            currentUser = (UserDetails) auth.getDetails();
	        } else {
	            throw new AccessDeniedException("User not properly authenticated.");
	        }
	        return currentUser;
	    }

	public List<Birth> getZoneBirthListByStatus(int zoneId,BirthStatusEnum birthStatusEnum,int count) {
		return birthDao.getZoneBirthListByStatus(zoneId, birthStatusEnum,count);
	}
	
	public List<Birth> getZoneBirthList(Birth birth) {
		return birthDao.getZoneBirthList(birth);
	}
	
	public List<Birth> searchBirth(Birth birth)
	{
		return birthDao.searchBirth(birth);
	}
	
	public List<Birth> searchBirthForAdminUser(Birth birth)
	{
		return birthDao.searchBirthForAdminUser(birth);
	}

	public String getNextBirthCounterForHospital(int hospitalId, int year) {
		int currentCountForYear = birthDao.getBirthCountForHospital(hospitalId, year);
		String value = year + "-" + prefixHospital(hospitalId) + "-" + prefixBirthId(currentCountForYear+1);
		return value;
		
	}
	
	private String prefixHospital(int value) {
		return String.format("%04d", value);
	}

	private String prefixBirthId(int value) {
		return String.format("%04d", value);
	}

	public StatisticsModel getHospitalStatisticsCount(int hospitalId,int months) {
		return birthDao.getHospitalStatisticsCount(hospitalId,months);
	}

	public StatisticsModel getZoneStatisticsCount(int zoneId,int months){
		return birthDao.getZoneStatisticsCount(zoneId,months);
	}
	public void updateDeliveryDetails(String id, Birth birth){
		 birthDao.updateDeliveryDetails(id, birth);
	}
	
	public StatisticsModel getMaleFemaleCount(int months){
		return birthDao.getMaleFemaleCount(months);
	}
	
	public Map<String, ArrayList<Integer>> getZoneMaleFemaleCountByMonths(int zoneId ,int months){
		
		Map<String, ArrayList<Integer>> countMap = new HashMap<String, ArrayList<Integer>>();
		List<Object[]> maleList = birthDao.getZoneMaleFemaleCountByMonths(zoneId, months, "Male");
		List<Object[]> femaleList = birthDao.getZoneMaleFemaleCountByMonths(zoneId, months, "Female");
		countMap = processMaleFemaleCount(maleList,femaleList);
		return countMap;
	}
	
	public Map<String, ArrayList<Integer>> getHospitalMaleFemaleCountByMonths(int hospitalId ,int months){
		Map<String, ArrayList<Integer>> countMap = new HashMap<String, ArrayList<Integer>>();
		List<Object[]> maleList = birthDao.getHospitalMaleFemaleCountByMonths(hospitalId, months, "Male");
		List<Object[]> femaleList = birthDao.getHospitalMaleFemaleCountByMonths(hospitalId, months, "Female");
		countMap = processMaleFemaleCount(maleList,femaleList);
		return countMap;
	}

	public List<Object[]> getAllZonesMaleFemaleCounts(int months){
		List<Object[]> objList = birthDao.getAllZonesMaleFemaleCounts(months);
		
		return objList;
	}
	
	private Map<String, ArrayList<Integer>> processMaleFemaleCount(List<Object[]> maleList ,List<Object[]> femaleList){
		Map<String, ArrayList<Integer>> countMap = new HashMap<String, ArrayList<Integer>>();
		
		Map<Object, Object[]> maleMap = new HashMap<Object, Object[]>();
		Map<Object, Object[]> femaleMap = new HashMap<Object, Object[]>();
		
		if(maleList != null && maleList.size()>0){
			for(int i=0; i<maleList.size(); i++){
				Object obj[] = maleList.get(i);
				maleMap.put(obj[2], obj);
			}
		}

		if(femaleList != null && femaleList.size()>0){
			for(int i=0; i<femaleList.size(); i++){
				Object obj[] = femaleList.get(i);
				femaleMap.put(obj[2], obj);
			}
		}
		String monthsArray[] = new DateFormatSymbols().getMonths();
		String pastMonths [] = new String[6];
		Calendar cal = Calendar.getInstance();  
		for(int i=0;i<6; i++){
			cal.setTime(new Date());
			cal.add(Calendar.MONTH,-i);
			pastMonths[i]=monthsArray[cal.get(Calendar.MONTH)]; 
		}
		ArrayList<Integer> maleCountList = new ArrayList<Integer>();
		ArrayList<Integer> femaleCountList = new ArrayList<Integer>();
		
		for(String month:pastMonths){
			if(maleMap.get(month) != null){
				Object obj[] = (Object[])maleMap.get(month);
				maleCountList.add(((BigInteger)obj[0]).intValue());
			}else{
				maleCountList.add(0);
			}
			if(femaleMap.get(month) != null){
				Object obj[] = (Object[])femaleMap.get(month);
				femaleCountList.add(((BigInteger)obj[0]).intValue());
			}else{
				femaleCountList.add(0);
			}
		}
		countMap.put("Male", maleCountList);
		countMap.put("Female", femaleCountList);
		return countMap;
	}
	public StatisticsModel getAllZoneStatisticsCount(int months){
		return birthDao.getAllZoneStatisticsCount(months);
	}
}
